﻿using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Zocono.Infrastructure.Common;
using Zocono.WCS.Comm;
using Zocono.WCS.Domain.DomainRepository;
using Zocono.WCS.Domain.EntityInfo;
using Zocono.WCS.Domain.FSJDomain;
using Zocono.WCS.Domain.LogDomain;
using Zocono.WCS.Domain.PlcBytesObject;
using Zocono.WCS.Domain.PlcConnectPoolDomain;
using Zocono.WCS.Domain.ProcessModuleDomain;
using Zocono.WCS.Infrastructure.ApllicationDto.Enums;
using Zocono.WCS.Infrastructure.ApllicationDto.FxModel;
using Zocono.WCS.Infrastructure.PlcCommon;
using Zocono.WCS.WMSApiDomain;
using Zocono.WCS.WMSApiDomain.WebApi;

namespace Zocono.WCS.Domain.EquipmentProcessDomain.PlanarGeneralMessage
{
    /// <summary>
    /// 组盘位空盘到达校验  组盘位握手 1-0
    /// </summary>
    public class FSJWorker_ZuPan_1Service : IPlanarGeneralPlcActionProcessService
    {
        private readonly IRedisHelper _IRedisHelper;
        private readonly ILogUtil _LogUtil;
        private readonly IPlcConnectionPool _PlcConnectionPool;
        private readonly IWorkTaskInfoRepository _WorkTaskInfoRepository;
        private readonly IPlcWriteDbInfoRepository _PlcWriteDbInfoRepository;
        private readonly IPlcConnectionInfoRepository _PlcConnectionInfoRepository;
        private readonly IPlcPointInfoRepositpry _IPlcPointInfoRepositpry;
        private readonly IPlcConnectionStateInfoRepository _IPlcConnectionStateInfoRepository;
        private readonly IRunLogInfoService _IRunLogInfoService;
        private readonly IFSJMesService _IFSJMesService;

        public FSJWorker_ZuPan_1Service(IRedisHelper iRedisHelper, ILogUtil logUtil
            , IPlcConnectionPool plcConnectionPool
            , IWorkTaskInfoRepository workTaskInfoRepository
            , IPlcWriteDbInfoRepository plcWriteDbInfoRepository
            , IPlcConnectionInfoRepository plcConnectionInfoRepository,
            IPlcPointInfoRepositpry plcPointInfoRepositpry
             , IPlcConnectionStateInfoRepository plcConnectionStateInfoRepository
            , IRunLogInfoService runLogInfoService,
            IFSJMesService iFSJMesService)
        {
            _IRedisHelper = iRedisHelper;
            _LogUtil = logUtil;
            _PlcConnectionPool = plcConnectionPool;
            _WorkTaskInfoRepository = workTaskInfoRepository;
            _PlcWriteDbInfoRepository = plcWriteDbInfoRepository;
            _PlcConnectionInfoRepository = plcConnectionInfoRepository;
            _IPlcPointInfoRepositpry = plcPointInfoRepositpry;
            _IPlcConnectionStateInfoRepository = plcConnectionStateInfoRepository;
            _IRunLogInfoService = runLogInfoService;
            _IFSJMesService = iFSJMesService;
        }

        public async Task ProcessActionMessageAsync(BytesObjectBase plcActionMessage, BytesObjectBase wcsActionMessage, EquipmentDbObject planarEquipmentDbObject/*, BytesObjectBase plcStateMassge*/)
        {
            /*
             * 处理逻辑
             * 1. 验证plc是否在线
             * 2. 验证设备是否报警
             * 3. 验证wcs任务,验证wcs当前任务节点是否结束节点
             * 4. 存在，则组织报文，写入plc
             * 5. 写入plc是否成功，成功，结束任务，上报wms,失败，不往下操作
             */
            var plcMessage = plcActionMessage as PlanarGeneralPlcActionBO;//Plc的动作报文
            var wcsMessage = wcsActionMessage as PlanarGeneralWcsActionBO;//Wcs的动作报文
            plcMessage.PalletBarcode = plcMessage.PalletBarcode.Trim();
            //var plcStateBo = plcStateMassge as PlcOnLineStateBO;//Plc在线离线报文 没有设备信息
            RunLogInfo runLogInfo = new RunLogInfo();
            runLogInfo.ContainerBarcode = plcMessage.PalletBarcode;
            runLogInfo.EquipmentCode = plcMessage.EquipmentCode;
            runLogInfo.RunType = "分选位空盘校验";

            runLogInfo.RunLog = "分选位空盘校验开始";

            var plcConn = _PlcConnectionPool.S7GetWritePlcConnection(plcMessage.PlcConnectionID);
            if (plcConn == null)
            {
                _LogUtil.Error($"分选位空盘校验：托盘【{plcMessage.PalletBarcode}】分选位空盘校验，PLC设备【{plcMessage.EquipmentCode}】,连接池无连接({plcMessage.PlcConnectionID})");
                return;
            }
            var plcIPStates = await _IPlcConnectionStateInfoRepository.GetFirstAsync(l => l.PlcConnectionID == plcMessage.PlcConnectionID && l.Connected == true);
            if (plcIPStates == null)
            {
                _LogUtil.Error($"分选位空盘校验：托盘【{plcMessage.PalletBarcode}】分选位空盘校验，PLC设备【{plcMessage.EquipmentCode}】,获取连接({plcMessage.PlcConnectionID})失败");
                return;
            }


            //4. 组织报文，写入plc
            var objectType = typeof(PlanarGeneralWriteWcsAction).Name;
            var writeConfig = await _PlcWriteDbInfoRepository.GetFirstAsync(s => s.EquipmentCode == plcMessage.EquipmentCode && s.ObjectType == objectType);
            if (writeConfig == null)
            {
                _LogUtil.Error($"分选位空盘校验：托盘【{plcMessage.PalletBarcode}】分选位空盘校验，PLC设备【{plcMessage.EquipmentCode}】,获取PLC写入配置失败！请检查配置！");
                return;
            }

            
            //plc报文什么握手类型则回什么握手类型
            PlanarGeneralWriteWcsAction writeBo = new PlanarGeneralWriteWcsAction(
                writeConfig.PlcConnectionId,
                writeConfig.ID,
                writeConfig.DbCode,
                writeConfig.DbStart,
                objectType,
                plcMessage.EquipmentCode.ToInt32(),
                plcMessage.ActionType,
                plcMessage.ToEquipmentCode,
                0,
                plcMessage.PalletBarcode,
                plcMessage.PalletType,
                alrmCode: 0);

            //校验plc信息是否有托盘码
            if (string.IsNullOrEmpty(plcMessage.PalletBarcode) || plcMessage.PalletBarcode.Length != 10)
            {
                writeBo.AlrmCode = 102;
                writeBo.ActionType = 99;
                var flag = await plcConn.WriteDbAsync(writeBo.DbCode, writeBo.DbStart, writeBo.Deserialize());
                _IRedisHelper.SetStringKey($"PLC-{plcMessage.EquipmentCode}", plcMessage.EquipmentCode.ToString() + plcMessage.AlrmCode, TimeSpan.FromSeconds(10));
                return;
            }

            //前面都通过，则任务开始
            writeBo.ActionType = plcMessage.ActionType;
            var writeResult = await plcConn.WriteDbAsync(writeBo.DbCode, writeBo.DbStart, writeBo.Deserialize());

            if (writeResult == false)
            {
                _LogUtil.Error($"分选位空盘校验：托盘【{plcMessage.PalletBarcode}】分选位空盘校验，PLC设备【{plcMessage.EquipmentCode}】,PLC(IP{plcConn.IP},写入报文失败");
                return;
            }

            runLogInfo.RunLog = $"分选位空盘校验：托盘【{plcMessage.PalletBarcode}】分选位空盘校验，PLC设备【{plcMessage.EquipmentCode}】分选位空盘校验处理成功，写入报文成功！报文内容：{JsonConvert.SerializeObject(writeBo)}";
            await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
            
        }
    }
}
